#ifndef _GEOMOBJECT_
#define _GEOMOBJECT_

#include <vl/VLd.h>
#include "moremath.h"
#include "string.h"
#ifdef WIN32
#include <windows.h>
#endif
#ifdef MACOSX
#include <Fl/glut.H>
#else
#include <GL/glu.h>
//#include <GL/glut.h>
#endif


class GeomObject{
public:
	enum ObjType {DEFAULT, BOX, SPHERE, ELLIPSOID, PLANE, CYLINDER, HEAD, MESH};

protected:
	Mat4d mTransform;	// stores the transform
	double mGLTransMat[16];	// store GL transform
	Vec4d mColor;		// color for gl draw

	void *mPhysObj;	// pointer to primitive if any
	ObjType mType;

	// texture params
	unsigned int mTexture;
	char *mTextureFileName;

public:
	GeomObject(){
		mTransform=vl_1;
		//mColor=Vec4d(0.0,0.0,1.0,1.0);
		mColor=Vec4d(0.9,0.9,0.9,1.0);
		mPhysObj=NULL;
		mType=DEFAULT;
		mTextureFileName = NULL;
	}
	virtual ~GeomObject(){}

	inline void setTexture(const char *_filename){
		mTextureFileName = new char[256];
		strcpy(mTextureFileName, _filename);
	}
	virtual bool isInside(Vec3d _pt)=0;
	virtual double getSignedDist(const Vec3d &inPoint)=0;
	virtual double getVolume()=0;
	virtual void setExtent(Vec3d)=0;
	// return new object by transforming by inverse of the given matrix
	virtual GeomObject* getObjApplyInvTransform(const Mat4d &_mat)=0;

	//// Convert a point from plane space to world space (2D -> 3D) and back
	//virtual Vec3d transformLocalToWorld( const Vec2d inPoint )=0;
	//virtual Vec2d transformWorldToLocal( const Vec3d worldPoint )=0;

	//// Get matrix that converts a point from plane space to world space (2D -> 3D)
	//// v3D = mat * (v2D , 1)
	//virtual Mat3d getLocalToWorldMatrix()=0;


	// apply the transform
	virtual void applyTransform(Mat4d &_trans){
		mTransform = _trans*mTransform;
	}
	virtual inline void translate(Vec3d _p){
		for(int i=0; i<3; i++) mTransform[i][3]+=_p[i];
	}
	inline Mat4d& getWorldTransform(){return mTransform;}

	inline Mat4d getInvWorldTransform(){
		Mat4d transM = getWorldTransform();
		sub(transM, 3, 3) = trans(sub(transM, 3, 3));	// transpose the rotation component R-> R^T
		sub(transM, 0, 3, 3, 1) = -sub(transM, 3, 3)*sub(transM, 0, 3, 3, 1);	// change the translation component t -> -R^T*t
		return transM;
	}
	// get the center of the geom
	Vec3d getCenter(){
		Vec3d v;
		for(int i=0; i<3; i++) v[i]=mTransform[i][3];
		return v;
	}

	inline void setPhysObject(void *p){mPhysObj=p;}
	inline void *getPhysObject(){return mPhysObj;}
	inline ObjType getType(){return mType;}

	// GL stuff
	inline void getGLTransform(){
		for(int x=0;x<4;x++){
			for(int y=0;y<4;y++){
				mGLTransMat[4*x+y]=mTransform[y][x];
			}
		}
	}

	inline Vec4d getColor(){return mColor;}
	inline void setColor(Vec4d _c){mColor=_c;}
	virtual void draw(Vec4d _color, bool _default){
		printf("should not be called: line %d, file %s\n", __LINE__, __FILE__);
	};
};

#endif
